home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / redakcyjne / programy / eM CLient 2.0.5952.0 Beta / setup.msi / eMClient.cab / ManualChmFile / skinsupport / madcaputilities.js < prev   
Text File  |  2009-09-08  |  64KB  |  2,814 lines

  1. // {{MadCap}} //////////////////////////////////////////////////////////////////
  2. // Copyright: MadCap Software, Inc - www.madcapsoftware.com ////////////////////
  3. ////////////////////////////////////////////////////////////////////////////////
  4. // <version>3.0.0.0</version>
  5. ////////////////////////////////////////////////////////////////////////////////
  6.  
  7. var gLoaded                    = false;
  8. var gOnloadFuncs            = new Array();
  9. var gPreviousOnloadFunction    = window.onload;
  10. var gReady                    = false;
  11.  
  12. if ( gPreviousOnloadFunction != null )
  13. {
  14.     gOnloadFuncs.push( gPreviousOnloadFunction );
  15. }
  16.  
  17. window.onload = function()
  18. {
  19.     gReady = true;
  20.     
  21.     MCGlobals.Init();
  22.     
  23.     FMCRegisterCallback( "MCGlobals", MCEventType.OnInit, OnMCGlobalsInit, null );
  24. };
  25.  
  26. function OnMCGlobalsInit( args )
  27. {
  28.     gLoaded = true;
  29.     
  30.     for ( var i = 0; i < gOnloadFuncs.length; i++ )
  31.     {
  32.         gOnloadFuncs[i]();
  33.     }
  34. }
  35.  
  36. var MCGlobals    = new function()
  37. {
  38.     // Private member variables
  39.     
  40.     var mSelf    = this;
  41.     
  42.     // Public properties
  43.  
  44.     this.SubsystemFile        = "Manual.xml";
  45.     this.SkinFolder            = "Data/SkinDefault/";
  46.     this.SkinTemplateFolder    = "Skin/";
  47.     this.DefaultStartTopic    = "Welcome.htm";
  48.     
  49.     this.Initialized        = false;
  50.     
  51.     this.RootFolder            = null;
  52.     this.RootFrame            = null;
  53.     this.ToolbarFrame        = null;
  54.     this.BodyFrame            = null;
  55.     this.NavigationFrame    = null;
  56.     this.TopicCommentsFrame    = null;
  57.     this.BodyCommentsFrame    = null;
  58.     this.PersistenceFrame    = null;
  59.     
  60.     // Private methods
  61.     
  62.     function InitRoot()
  63.     {
  64.         mSelf.RootFrame = window;
  65.         mSelf.ToolbarFrame = frames["mctoolbar"];
  66.         mSelf.BodyFrame = frames["body"];
  67.         mSelf.NavigationFrame = frames["navigation"];
  68.         mSelf.PersistenceFrame = null;
  69.         
  70.         //
  71.         
  72.         var bodyReady    = false;
  73.         
  74.         FMCRegisterCallback( "Navigation", MCEventType.OnReady, OnNavigationReady, null );
  75.         
  76.         function OnNavigationReady( args )
  77.         {
  78.             mSelf.TopicCommentsFrame = mSelf.NavigationFrame.frames["topiccomments"];
  79.             
  80.             //
  81.             
  82.             if ( bodyReady )
  83.             {
  84.                 mSelf.Initialized = true;
  85.             }
  86.         }
  87.         
  88.         FMCRegisterCallback( "Body", MCEventType.OnReady, OnBodyReady, null );
  89.             
  90.         function OnBodyReady( args )
  91.         {
  92.             mSelf.BodyCommentsFrame = mSelf.BodyFrame.frames["topiccomments"];
  93.             
  94.             //
  95.             
  96.             bodyReady = true;
  97.             
  98.             if ( mSelf.TopicCommentsFrame != null )
  99.             {
  100.                 mSelf.Initialized = true;
  101.             }
  102.         }
  103.     }
  104.     
  105.     function InitTopicCHM()
  106.     {
  107.         mSelf.RootFrame = null;
  108.         mSelf.ToolbarFrame = frames["mctoolbar"];
  109.         mSelf.BodyFrame = window;
  110.         mSelf.NavigationFrame = null;
  111.         mSelf.TopicCommentsFrame = null;
  112.         mSelf.BodyCommentsFrame = frames["topiccomments"];
  113.         mSelf.PersistenceFrame = frames["persistence"];
  114.         
  115.         //
  116.             
  117.         mSelf.Initialized = true;
  118.     }
  119.     
  120.     function InitNavigation()
  121.     {
  122.         mSelf.RootFrame = parent;
  123.         mSelf.NavigationFrame = window;
  124.         mSelf.TopicCommentsFrame = frames["topiccomments"];
  125.         mSelf.PersistenceFrame = null;
  126.         
  127.         FMCRegisterCallback( "Root", MCEventType.OnReady, OnRootReady, null );
  128.             
  129.         function OnRootReady( args )
  130.         {
  131.             mSelf.ToolbarFrame = mSelf.RootFrame.frames["mctoolbar"];
  132.             mSelf.BodyFrame = mSelf.RootFrame.frames["body"];
  133.             
  134.             FMCRegisterCallback( "Body", MCEventType.OnReady, OnBodyReady, null );
  135.             
  136.             function OnBodyReady( args )
  137.             {
  138.                 mSelf.BodyCommentsFrame = mSelf.BodyFrame.frames["topiccomments"];
  139.                 
  140.                 //
  141.                 
  142.                 mSelf.Initialized = true;
  143.             }
  144.         }
  145.     }
  146.     
  147.     function InitNavigationFramesWebHelp()
  148.     {
  149.         var bodyReady    = false;
  150.         
  151.         mSelf.RootFrame = parent.parent;
  152.         mSelf.NavigationFrame = parent;
  153.         mSelf.PersistenceFrame = null;
  154.         
  155.         FMCRegisterCallback( "Root", MCEventType.OnReady, OnRootReady, null );
  156.             
  157.         function OnRootReady( args )
  158.         {
  159.             mSelf.ToolbarFrame = mSelf.RootFrame.frames["mctoolbar"];
  160.             mSelf.BodyFrame = mSelf.RootFrame.frames["body"];
  161.             
  162.             FMCRegisterCallback( "Body", MCEventType.OnReady, OnBodyReady, null );
  163.             
  164.             function OnBodyReady( args )
  165.             {
  166.                 mSelf.BodyCommentsFrame = mSelf.BodyFrame.frames["topiccomments"];
  167.                 
  168.                 //
  169.                 
  170.                 bodyReady = true;
  171.                 
  172.                 if ( mSelf.TopicCommentsFrame != null )
  173.                 {
  174.                     mSelf.Initialized = true;
  175.                 }
  176.             }
  177.         }
  178.         
  179.         FMCRegisterCallback( "Navigation", MCEventType.OnReady, OnNavigationReady, null );
  180.             
  181.         function OnNavigationReady( args )
  182.         {
  183.             mSelf.TopicCommentsFrame = mSelf.NavigationFrame.frames["topiccomments"];
  184.             
  185.             //
  186.             
  187.             if ( bodyReady )
  188.             {
  189.                 mSelf.Initialized = true;
  190.             }
  191.         }
  192.     }
  193.     
  194.     function InitBodyCommentsFrameWebHelp()
  195.     {
  196.         mSelf.RootFrame = parent.parent;
  197.         mSelf.NavigationFrame = parent.parent.frames["navigation"];
  198.         mSelf.PersistenceFrame = null;
  199.         mSelf.ToolbarFrame = parent.parent.frames["mctoolbar"];
  200.         mSelf.BodyFrame = parent;
  201.         mSelf.BodyCommentsFrame = window;
  202.         
  203.         FMCRegisterCallback( "Navigation", MCEventType.OnReady, OnNavigationReady, null );
  204.             
  205.         function OnNavigationReady( args )
  206.         {
  207.             mSelf.TopicCommentsFrame = mSelf.NavigationFrame.frames["topiccomments"];
  208.             
  209.             //
  210.             
  211.             mSelf.Initialized = true;
  212.         }
  213.     }
  214.     
  215.     function InitBodyCommentsFrameDotNetHelp()
  216.     {
  217.         mSelf.RootFrame = null;
  218.         mSelf.ToolbarFrame = null;
  219.         mSelf.BodyFrame = parent;
  220.         mSelf.NavigationFrame = null;
  221.         mSelf.TopicCommentsFrame = null;
  222.         mSelf.BodyCommentsFrame = window;
  223.         mSelf.PersistenceFrame = null;
  224.  
  225.         //
  226.  
  227.         mSelf.Initialized = true;
  228.     }
  229.     
  230.     function InitToolbarWebHelp()
  231.     {
  232.         mSelf.RootFrame = parent;
  233.         mSelf.ToolbarFrame = window;
  234.         mSelf.PersistenceFrame = null;
  235.         
  236.         FMCRegisterCallback( "Root", MCEventType.OnReady, OnRootReady, null );
  237.             
  238.         function OnRootReady( args )
  239.         {
  240.             mSelf.BodyFrame = mSelf.RootFrame.frames["body"];
  241.             mSelf.NavigationFrame = mSelf.RootFrame.frames["navigation"];
  242.             
  243.             //
  244.             
  245.             var bodyReady    = false;
  246.             
  247.             FMCRegisterCallback( "Navigation", MCEventType.OnReady, OnNavigationReady, null );
  248.             
  249.             function OnNavigationReady( args )
  250.             {
  251.                 mSelf.TopicCommentsFrame = mSelf.NavigationFrame.frames["topiccomments"];
  252.                 
  253.                 //
  254.                 
  255.                 if ( bodyReady )
  256.                 {
  257.                     mSelf.Initialized = true;
  258.                 }
  259.             }
  260.             
  261.             FMCRegisterCallback( "Body", MCEventType.OnReady, OnBodyReady, null );
  262.             
  263.             function OnBodyReady( args )
  264.             {
  265.                 mSelf.BodyCommentsFrame = mSelf.BodyFrame.frames["topiccomments"];
  266.                 
  267.                 //
  268.                 
  269.                 bodyReady = true;
  270.                 
  271.                 if ( mSelf.TopicCommentsFrame != null )
  272.                 {
  273.                     mSelf.Initialized = true;
  274.                 }
  275.             }
  276.         }
  277.     }
  278.     
  279.     function InitToolbarCHM()
  280.     {
  281.         mSelf.RootFrame = null;
  282.         mSelf.ToolbarFrame = window;
  283.         mSelf.BodyFrame = parent;
  284.         mSelf.NavigationFrame = null;
  285.         mSelf.TopicCommentsFrame = null;
  286.         
  287.         FMCRegisterCallback( "Body", MCEventType.OnReady, OnBodyReady, null );
  288.             
  289.         function OnBodyReady( args )
  290.         {
  291.             mSelf.BodyCommentsFrame = mSelf.BodyFrame.frames["topiccomments"];
  292.             mSelf.PersistenceFrame = mSelf.BodyFrame.frames["persistence"];
  293.             
  294.             //
  295.         
  296.             mSelf.Initialized = true;
  297.         }
  298.     }
  299.     
  300.     function InitTopicWebHelp()
  301.     {
  302.         mSelf.RootFrame = parent;
  303.         mSelf.BodyFrame = window;
  304.         mSelf.BodyCommentsFrame = mSelf.BodyFrame.frames["topiccomments"];
  305.         mSelf.PersistenceFrame = null;
  306.         
  307.         FMCRegisterCallback( "Root", MCEventType.OnReady, OnRootReady, null );
  308.         
  309.         function OnRootReady( args )
  310.         {
  311.             mSelf.ToolbarFrame = mSelf.RootFrame.frames["mctoolbar"];
  312.             mSelf.NavigationFrame = mSelf.RootFrame.frames["navigation"];
  313.             
  314.             FMCRegisterCallback( "Navigation", MCEventType.OnReady, OnNavigationReady, null );
  315.             
  316.             function OnNavigationReady( args )
  317.             {
  318.                 mSelf.TopicCommentsFrame = mSelf.NavigationFrame.frames["topiccomments"];
  319.                 
  320.                 //
  321.             
  322.                 mSelf.Initialized = true;
  323.             }
  324.         }
  325.     }
  326.     
  327.     function InitTopicDotNetHelp()
  328.     {
  329.         mSelf.RootFrame = null;
  330.         mSelf.ToolbarFrame = null;
  331.         mSelf.BodyFrame = window;
  332.         mSelf.NavigationFrame = null;
  333.         mSelf.TopicCommentsFrame = null;
  334.         mSelf.BodyCommentsFrame = mSelf.BodyFrame.frames["topiccomments"];
  335.         mSelf.PersistenceFrame = null;
  336.  
  337.         //
  338.  
  339.         mSelf.Initialized = true;
  340.     }
  341.     
  342.     function InitNavigationFramesCHM()
  343.     {
  344.         mSelf.RootFrame = null;
  345.         mSelf.BodyFrame = parent;
  346.         mSelf.NavigationFrame = null;
  347.         mSelf.TopicCommentsFrame = null;
  348.         
  349.         FMCRegisterCallback( "Body", MCEventType.OnReady, OnBodyReady, null );
  350.             
  351.         function OnBodyReady( args )
  352.         {
  353.             mSelf.ToolbarFrame = mSelf.BodyFrame.frames["mctoolbar"];
  354.             mSelf.BodyCommentsFrame = mSelf.BodyFrame.frames["topiccomments"];
  355.             mSelf.PersistenceFrame = mSelf.BodyFrame.frames["persistence"];
  356.             
  357.             //
  358.         
  359.             mSelf.Initialized = true;
  360.         }
  361.     }
  362.     
  363.     // Public methods
  364.     
  365.     this.Init    = function()
  366.     {
  367.         if ( FMCInPreviewMode() )
  368.         {
  369.             mSelf.Initialized = true;
  370.             
  371.             return;
  372.         }
  373.         
  374.         if ( frames["mctoolbar"] != null )    // Root or topic in CHM
  375.         {
  376.             mSelf.ToolbarFrame = frames["mctoolbar"];
  377.             
  378.             if ( frames["body"] != null )    // Root
  379.             {
  380.                 InitRoot();
  381.             }
  382.             else                            // Topic in CHM
  383.             {
  384.                 InitTopicCHM();
  385.             }
  386.         }
  387.         else if ( window.name == "navigation" )    // Navigation
  388.         {
  389.             InitNavigation();
  390.         }
  391.         else if ( parent.name == "navigation" )    // Navigation frames in WebHelp
  392.         {
  393.             InitNavigationFramesWebHelp();
  394.         }
  395.         else if ( window.name == "mctoolbar" )    // Toolbar
  396.         {
  397.             mSelf.ToolbarFrame = window;
  398.             
  399.             if ( parent.frames["navigation"] != null )    // Toolbar in WebHelp
  400.             {
  401.                 InitToolbarWebHelp();
  402.             }
  403.             else                                        // Toolbar in CHM
  404.             {
  405.                 InitToolbarCHM();
  406.             }
  407.         }
  408.         else if ( window.name == "body" )    // Topic in WebHelp
  409.         {
  410.             if ( FMCIsWebHelp() )
  411.             {
  412.                 InitTopicWebHelp();
  413.             }
  414.             else if ( FMCIsDotNetHelp() )
  415.             {
  416.                 InitTopicDotNetHelp();
  417.             }
  418.             else if ( FMCIsHtmlHelp() )
  419.             {
  420.                 InitTopicCHM();
  421.             }
  422.         }
  423.         else if ( window.name == "topiccomments" )
  424.         {
  425.             if ( parent.name != "body" )
  426.             {
  427.                 mSelf.Initialized = true;
  428.                 
  429.                 return;
  430.             }
  431.             
  432.             if ( FMCIsHtmlHelp() )
  433.             {
  434.                 InitNavigationFramesCHM();    // Body comments frame in CHM
  435.             }
  436.             else if ( FMCIsWebHelp() )
  437.             {
  438.                 InitBodyCommentsFrameWebHelp();    // Body comments frame in WebHelp body
  439.             }
  440.             else if ( FMCIsDotNetHelp() )
  441.             {
  442.                 InitBodyCommentsFrameDotNetHelp();    // Body comments frame in DotNet Help body
  443.             }
  444.         }
  445.         else if (    window.name == "toc" ||
  446.                     window.name == "index" ||
  447.                     window.name == "search" ||
  448.                     window.name == "glossary" ||
  449.                     window.name == "favorites" ||
  450.                     window.name == "browsesequences" ||
  451.                     window.name == "recentcomments" )    // Navigation frames in CHM
  452.         {
  453.             InitNavigationFramesCHM();
  454.         }
  455.         else if ( FMCIsDotNetHelp() )
  456.         {
  457.             mSelf.Initialized = true;
  458.         }
  459.         else
  460.         {
  461.             mSelf.Initialized = true;
  462.             
  463.             return;
  464.         }
  465.         
  466.         if ( FMCIsWebHelp() )
  467.         {
  468.             var rootFolder    = mSelf.RootFrame.document.location.href.substring( 0, mSelf.RootFrame.document.location.href.lastIndexOf( "/" ) + 1 );
  469.             var subFolder    = document.location.href.substring( 0, document.location.href.lastIndexOf( "/" ) + 1 );
  470.             
  471.             if ( subFolder.StartsWith( rootFolder + "Subsystems", false ) )
  472.             {
  473.                 var href    = document.location.href;
  474.                 var subPart    = document.location.href.substring( (rootFolder + "Subsystems").length + 1 );
  475.                 
  476.                 subPart = subPart.substring( 0, subPart.indexOf( "/" ) + 1 );
  477.                 rootFolder = rootFolder + "Subsystems/" + subPart;
  478.                 
  479.                 rootFolder = rootFolder.replace( /\\/g, "/" );
  480.                 rootFolder = rootFolder.replace( /%20/g, " " );
  481.                 rootFolder = rootFolder.replace( /;/g, "%3B" );    // For Safari
  482.                 
  483.                 mSelf.RootFolder = rootFolder;
  484.             }
  485.             else if ( subFolder.StartsWith( rootFolder + "AutoMerge", false ) )
  486.             {
  487.                 var href    = document.location.href;
  488.                 var subPart    = document.location.href.substring( (rootFolder + "AutoMerge").length + 1 );
  489.                 
  490.                 subPart = subPart.substring( 0, subPart.indexOf( "/" ) + 1 );
  491.                 rootFolder = rootFolder + "AutoMerge/" + subPart;
  492.                 
  493.                 rootFolder = rootFolder.replace( /\\/g, "/" );
  494.                 rootFolder = rootFolder.replace( /%20/g, " " );
  495.                 rootFolder = rootFolder.replace( /;/g, "%3B" );    // For Safari
  496.                 
  497.                 mSelf.RootFolder = rootFolder;
  498.             }
  499.             else
  500.             {
  501.                 mSelf.RootFolder = FMCGetRootFolder( mSelf.RootFrame.document.location );
  502.             }
  503.         }
  504.         else if ( FMCIsHtmlHelp() )
  505.         {
  506.             mSelf.RootFolder = "/";
  507.         }
  508.         else if ( FMCIsDotNetHelp() )
  509.         {
  510.             var rootFolder    = FMCGetRootFolder( mSelf.BodyFrame.document.location );
  511.             
  512.             mSelf.RootFolder = rootFolder.substring( 0, rootFolder.lastIndexOf( "/", rootFolder.length - 2 ) + 1 );
  513.         }
  514.     }
  515. }
  516.  
  517. //
  518. //    Helper functions
  519. //
  520.  
  521. var gImages    = new Array();
  522.  
  523. function FMCIsWebHelp()
  524. {
  525.     return FMCGetRootFrame() != null;
  526. }
  527.  
  528. function FMCIsHtmlHelp()
  529. {
  530.     var href    = document.location.href;
  531.     
  532.     return href.indexOf( "mk:" ) == 0;
  533. }
  534.  
  535. function FMCIsDotNetHelp()
  536. {
  537.     return FMCGetRootFrame() == null && !FMCIsHtmlHelp();
  538. }
  539.  
  540. function FMCIsTopicPopup()
  541. {
  542.     return window.parent != window && window.parent.name == "body";
  543. }
  544.  
  545. var gLiveHelpEnabled    = null;
  546.  
  547. function FMCIsLiveHelpEnabled()
  548. {
  549.     if ( gLiveHelpEnabled == null )
  550.     {
  551.         var xmlDoc        = CMCXmlParser.GetXmlDoc( MCGlobals.RootFolder + MCGlobals.SubsystemFile, false, null, null );
  552.         
  553.         if ( xmlDoc == null )
  554.         {
  555.             gLiveHelpEnabled = false;
  556.         }
  557.         else
  558.         {
  559.             var projectID    = xmlDoc.documentElement.getAttribute( "LiveHelpOutputId" );
  560.             
  561.             gLiveHelpEnabled = projectID != null;
  562.         }
  563.     }
  564.     
  565.     return gLiveHelpEnabled;
  566. }
  567.  
  568. function FMCInPreviewMode()
  569. {
  570.     return FMCGetRootFrame() == null && !FMCIsHtmlHelp();
  571. }
  572.  
  573. var gSkinPreviewMode    = null;
  574.  
  575. function FMCIsSkinPreviewMode()
  576. {
  577.     if ( gSkinPreviewMode == null )
  578.     {
  579.         var xmlDoc        = CMCXmlParser.GetXmlDoc( MCGlobals.RootFolder + MCGlobals.SubsystemFile, false, null, null );
  580.         
  581.         if ( xmlDoc == null )
  582.         {
  583.             gSkinPreviewMode = false;
  584.         }
  585.         else
  586.         {
  587.             gSkinPreviewMode = FMCGetAttributeBool( xmlDoc.documentElement, "SkinPreviewMode", false );
  588.         }
  589.     }
  590.     
  591.     return gSkinPreviewMode;
  592. }
  593.  
  594. function FMCIsIE55()
  595. {
  596.     return navigator.appVersion.indexOf( "MSIE 5.5" ) != -1;
  597. }
  598.  
  599. function FMCIsSafari()
  600. {
  601.     return typeof( document.clientHeight ) != "undefined";
  602. }
  603.  
  604. function FMCGetSkinFolder()
  605. {
  606.     var skinFolder    = null;
  607.     
  608.     if ( MCGlobals.RootFrame != null )
  609.     {
  610.         skinFolder = MCGlobals.RootFrame.gSkinFolder;
  611.     }
  612.     else
  613.     {
  614.         skinFolder = MCGlobals.SkinFolder;
  615.     }
  616.     
  617.     return skinFolder;
  618. }
  619.  
  620. function FMCGetHref( currLocation )
  621. {
  622.     var href    = currLocation.protocol + (!FMCIsHtmlHelp() ? "//" : "") + currLocation.host + currLocation.pathname;
  623.  
  624.     href = FMCEscapeHref( href );
  625.  
  626.     return href;
  627. }
  628.  
  629. function FMCEscapeHref( href )
  630. {
  631.     var newHref    = href.replace( /\\/g, "/" );
  632.     newHref = newHref.replace( /%20/g, " " );
  633.     newHref = newHref.replace( /;/g, "%3B" );    // For Safari
  634.  
  635.     return newHref;
  636. }
  637.  
  638. function FMCGetRootFolder( currLocation )
  639. {
  640.     var href        = FMCGetHref( currLocation );
  641.     var rootFolder    = href.substring( 0, href.lastIndexOf( "/" ) + 1 );
  642.  
  643.     return rootFolder;
  644. }
  645.  
  646. function FMCGetPathnameFolder( currLocation )
  647. {
  648.     var pathname    = currLocation.pathname;
  649.  
  650.     // This is for when viewing over a network. IE needs the path to be like this.
  651.  
  652.     if ( currLocation.protocol.StartsWith( "file" ) )
  653.     {
  654.         if ( !currLocation.host.IsNullOrEmpty() )
  655.         {
  656.             pathname = "/" + currLocation.host + currLocation.pathname;
  657.         }
  658.     }
  659.  
  660.     //
  661.  
  662.     pathname = pathname.replace( /\\/g, "/" );
  663.     //pathname = pathname.replace( /%20/g, " " );
  664.     pathname = pathname.replace( /;/g, "%3B" );    // For Safari
  665.     pathname = pathname.substring( 0, pathname.lastIndexOf( "/" ) + 1 );
  666.  
  667.     return pathname;
  668. }
  669.  
  670. function FMCGetRootFrame()
  671. {
  672.     var currWindow    = window;
  673.     
  674.     while ( currWindow )
  675.     {
  676.         if ( currWindow.gRootFolder )
  677.         {
  678.             break;
  679.         }
  680.         else if ( currWindow == top )
  681.         {
  682.             currWindow = null;
  683.             
  684.             break;
  685.         }
  686.         
  687.         currWindow = currWindow.parent;
  688.     }
  689.     
  690.     return currWindow;
  691. }
  692.  
  693. function FMCPreloadImage( imgPath )
  694. {
  695.     if ( imgPath == null )
  696.     {
  697.         return;
  698.     }
  699.     
  700.     if ( imgPath.StartsWith( "url", false ) && imgPath.EndsWith( ")", false ) )
  701.     {
  702.         imgPath = FMCStripCssUrl( imgPath );
  703.     }
  704.     
  705.     var index    = gImages.length;
  706.     
  707.     gImages[index] = new Image();
  708.     gImages[index].src = imgPath;
  709. }
  710.  
  711. function FMCTrim( str )
  712. {
  713.     return FMCLTrim( FMCRTrim( str ) );
  714. }
  715.  
  716. function FMCLTrim( str )
  717. {
  718.     for ( var i = 0; i < str.length && str.charAt( i ) == " "; i++ );
  719.     
  720.     return str.substring( i, str.length );
  721. }
  722.  
  723. function FMCRTrim( str )
  724. {
  725.     for ( var i = str.length - 1; i >= 0 && str.charAt( i ) == " "; i-- );
  726.     
  727.     return str.substring( 0, i + 1 );
  728. }
  729.  
  730. function FMCContainsClassRoot( className )
  731. {
  732.     var ret = null;
  733.     
  734.     for ( var i = 1; i < FMCContainsClassRoot.arguments.length; i++ )
  735.     {
  736.         var classRoot = arguments[i];
  737.         
  738.         if ( className && (className == classRoot || className.indexOf( classRoot + "_" ) == 0) )
  739.         {
  740.             ret = classRoot;
  741.             
  742.             break;
  743.         }
  744.     }
  745.     
  746.     return ret;
  747. }
  748.  
  749. function FMCGetChildNodeByTagName( node, tagName, index )
  750. {
  751.     var foundNode   = null;
  752.     var numFound    = -1;
  753.     
  754.     for ( var currNode = node.firstChild; currNode != null; currNode = currNode.nextSibling )
  755.     {
  756.         if ( currNode.nodeName == tagName )
  757.         {
  758.             numFound++;
  759.             
  760.             if ( numFound == index )
  761.             {
  762.                 foundNode = currNode;
  763.                 
  764.                 break;
  765.             }
  766.         }
  767.     }
  768.     
  769.     return foundNode;
  770. }
  771.  
  772. function FMCGetChildNodesByTagName( node, tagName )
  773. {
  774.     var nodes   = new Array();
  775.     
  776.     for ( var i = 0; i < node.childNodes.length; i++ )
  777.     {
  778.         if ( node.childNodes[i].nodeName == tagName )
  779.         {
  780.             nodes[nodes.length] = node.childNodes[i];
  781.         }
  782.     }
  783.     
  784.     return nodes;
  785. }
  786.  
  787. function FMCStringToBool( stringValue )
  788. {
  789.     var boolValue        = false;
  790.     var stringValLower    = stringValue.toLowerCase();
  791.  
  792.     boolValue = stringValLower == "true" || stringValLower == "1" || stringValLower == "yes";
  793.  
  794.     return boolValue;
  795. }
  796.  
  797. function FMCGetAttributeBool( node, attributeName, defaultValue )
  798. {
  799.     var boolValue    = defaultValue;
  800.     var value        = FMCGetAttribute( node, attributeName );
  801.     
  802.     if ( value )
  803.     {
  804.         boolValue = FMCStringToBool( value );
  805.     }
  806.     
  807.     return boolValue;
  808. }
  809.  
  810. function FMCGetAttributeInt( node, attributeName, defaultValue )
  811. {
  812.     var intValue    = defaultValue;
  813.     var value        = FMCGetAttribute( node, attributeName );
  814.     
  815.     if ( value != null )
  816.     {
  817.         intValue = parseInt( value );
  818.     }
  819.     
  820.     return intValue;
  821. }
  822.  
  823. function FMCGetAttribute( node, attribute )
  824. {
  825.     var value   = null;
  826.     
  827.     if ( node.getAttribute( attribute ) != null )
  828.     {
  829.         value = node.getAttribute( attribute );
  830.     }
  831.     else if ( node.getAttribute( attribute.toLowerCase() ) != null )
  832.     {
  833.         value = node.getAttribute( attribute.toLowerCase() );
  834.     }
  835.     else
  836.     {
  837.         var namespaceIndex    = attribute.indexOf( ":" );
  838.         
  839.         if ( namespaceIndex != -1 )
  840.         {
  841.             value = node.getAttribute( attribute.substring( namespaceIndex + 1, attribute.length ) );
  842.         }
  843.     }
  844.     
  845.     if ( typeof( value ) == "string" && value == "" )
  846.     {
  847.         value = null;
  848.     }
  849.     
  850.     return value;
  851. }
  852.  
  853. function FMCGetMCAttribute( node, attribute )
  854. {
  855.     var value    = null;
  856.     
  857.     if ( node.getAttribute( attribute ) != null )
  858.     {
  859.         value = node.getAttribute( attribute );
  860.     }
  861.     else if ( node.getAttribute( attribute.substring( "MadCap:".length, attribute.length ) ) )
  862.     {
  863.         value = node.getAttribute( attribute.substring( "MadCap:".length, attribute.length ) );
  864.     }
  865.     
  866.     return value;
  867. }
  868.  
  869. function FMCRemoveMCAttribute( node, attribute )
  870. {
  871.     var value    = null;
  872.     
  873.     if ( node.getAttribute( attribute ) != null )
  874.     {
  875.         value = node.removeAttribute( attribute );
  876.     }
  877.     else if ( node.getAttribute( attribute.substring( "MadCap:".length, attribute.length ) ) )
  878.     {
  879.         value = node.removeAttribute( attribute.substring( "MadCap:".length, attribute.length ) );
  880.     }
  881.     
  882.     return value;
  883. }
  884.  
  885. function FMCGetClientWidth( winNode, includeScrollbars )
  886. {
  887.     var clientWidth = null;
  888.     
  889.     if ( typeof( winNode.innerWidth ) != "undefined" )
  890.     {
  891.         clientWidth = winNode.innerWidth;
  892.         
  893.         if ( !includeScrollbars && FMCGetScrollHeight( winNode ) > winNode.innerHeight )
  894.         {
  895.             clientWidth -= 19;
  896.         }
  897.     }
  898.     else if ( FMCIsIE55() || (winNode.document.compatMode && winNode.document.compatMode == "BackCompat") )
  899.     {
  900.         clientWidth = winNode.document.body.clientWidth;
  901.     }
  902.     else if ( winNode.document.documentElement )
  903.     {
  904.         clientWidth = winNode.document.documentElement.clientWidth;
  905.     }
  906.     
  907.     return clientWidth;
  908. }
  909.  
  910. function FMCGetClientHeight( winNode, includeScrollbars )
  911. {
  912.     var clientHeight    = null;
  913.     
  914.     if ( typeof( winNode.innerHeight ) != "undefined" )
  915.     {
  916.         clientHeight = winNode.innerHeight;
  917.         
  918.         if ( !includeScrollbars && FMCGetScrollWidth( winNode ) > winNode.innerWidth )
  919.         {
  920.             clientHeight -= 19;
  921.         }
  922.     }
  923.     else if ( FMCIsIE55() || (winNode.document.compatMode && winNode.document.compatMode == "BackCompat") )
  924.     {
  925.         clientHeight = winNode.document.body.clientHeight;
  926.     }
  927.     else if ( winNode.document.documentElement )
  928.     {
  929.         clientHeight = winNode.document.documentElement.clientHeight;
  930.     }
  931.     
  932.     return clientHeight;
  933. }
  934.  
  935. function FMCGetClientCenter( winNode )
  936. {
  937.     var centerX    = FMCGetScrollLeft( winNode ) + (FMCGetClientWidth( winNode, false ) / 2);
  938.     var centerY    = FMCGetScrollTop( winNode ) + (FMCGetClientHeight( winNode, false ) / 2);
  939.     
  940.     return [centerX, centerY];
  941. }
  942.  
  943. function FMCGetScrollHeight( winNode )
  944. {
  945.     var scrollHeight    = null;
  946.     
  947.     if ( winNode.document.scrollHeight )
  948.     {
  949.         scrollHeight = winNode.document.scrollHeight;
  950.     }
  951.     else if ( FMCIsIE55() || (winNode.document.compatMode && winNode.document.compatMode == "BackCompat") )
  952.     {
  953.         scrollHeight = winNode.document.body.scrollHeight;
  954.     }
  955.     else if ( winNode.document.documentElement )
  956.     {
  957.         scrollHeight = winNode.document.documentElement.scrollHeight;
  958.     }
  959.     
  960.     return scrollHeight;
  961. }
  962.  
  963. function FMCGetScrollWidth( winNode )
  964. {
  965.     var scrollWidth = null;
  966.     
  967.     if ( winNode.document.scrollWidth )
  968.     {
  969.         scrollWidth = winNode.document.scrollWidth;
  970.     }
  971.     else if ( FMCIsIE55() || (winNode.document.compatMode && winNode.document.compatMode == "BackCompat") )
  972.     {
  973.         scrollWidth = winNode.document.body.scrollWidth;
  974.     }
  975.     else if ( winNode.document.documentElement )
  976.     {
  977.         scrollWidth = winNode.document.documentElement.scrollWidth;
  978.     }
  979.     
  980.     return scrollWidth;
  981. }
  982.  
  983. function FMCGetScrollTop( winNode )
  984. {
  985.     var scrollTop   = null;
  986.     
  987.     if ( FMCIsSafari() )
  988.     {
  989.         scrollTop = winNode.document.body.scrollTop;
  990.     }
  991.     else if ( FMCIsIE55() || (winNode.document.compatMode && winNode.document.compatMode == "BackCompat") )
  992.     {
  993.         scrollTop = winNode.document.body.scrollTop;
  994.     }
  995.     else if ( winNode.document.documentElement )
  996.     {
  997.         scrollTop = winNode.document.documentElement.scrollTop;
  998.     }
  999.     
  1000.     return scrollTop;
  1001. }
  1002.  
  1003. function FMCSetScrollTop( winNode, value )
  1004. {
  1005.     if ( FMCIsSafari() )
  1006.     {
  1007.         winNode.document.body.scrollTop = value;
  1008.     }
  1009.     else if ( FMCIsIE55() || (winNode.document.compatMode && winNode.document.compatMode == "BackCompat") )
  1010.     {
  1011.         winNode.document.body.scrollTop = value;
  1012.     }
  1013.     else if ( winNode.document.documentElement )
  1014.     {
  1015.         winNode.document.documentElement.scrollTop = value;
  1016.     }
  1017. }
  1018.  
  1019. function FMCGetScrollLeft( winNode )
  1020. {
  1021.     var scrollLeft  = null;
  1022.     
  1023.     if ( FMCIsSafari() )
  1024.     {
  1025.         scrollLeft = winNode.document.body.scrollLeft;
  1026.     }
  1027.     else if ( FMCIsIE55() || (winNode.document.compatMode && winNode.document.compatMode == "BackCompat") )
  1028.     {
  1029.         scrollLeft = winNode.document.body.scrollLeft;
  1030.     }
  1031.     else if ( winNode.document.documentElement )
  1032.     {
  1033.         scrollLeft = winNode.document.documentElement.scrollLeft;
  1034.     }
  1035.     
  1036.     return scrollLeft;
  1037. }
  1038.  
  1039. function FMCSetScrollLeft( winNode, value )
  1040. {
  1041.     if ( FMCIsSafari() )
  1042.     {
  1043.         winNode.document.body.scrollLeft = value;
  1044.     }
  1045.     else if ( FMCIsIE55() || (winNode.document.compatMode && winNode.document.compatMode == "BackCompat") )
  1046.     {
  1047.         winNode.document.body.scrollLeft = value;
  1048.     }
  1049.     else if ( winNode.document.documentElement )
  1050.     {
  1051.         winNode.document.documentElement.scrollLeft = value;
  1052.     }
  1053. }
  1054.  
  1055. function FMCGetClientX( winNode, e )
  1056. {
  1057.     var clientX;
  1058.     
  1059.     if ( typeof( e.pageX ) != "undefined" )
  1060.     {
  1061.         clientX = e.pageX - FMCGetScrollLeft( winNode );
  1062.     }
  1063.     else if ( typeof( e.clientX ) != "undefined" )
  1064.     {
  1065.         clientX = e.clientX;
  1066.     }
  1067.     
  1068.     return clientX;
  1069. }
  1070.  
  1071. function FMCGetClientY( winNode, e )
  1072. {
  1073.     var clientY;
  1074.     
  1075.     if ( typeof( e.pageY ) != "undefined" )
  1076.     {
  1077.         clientY = e.pageY - FMCGetScrollTop( winNode );
  1078.     }
  1079.     else if ( typeof( e.clientY ) != "undefined" )
  1080.     {
  1081.         clientY = e.clientY;
  1082.     }
  1083.     
  1084.     return clientY;
  1085. }
  1086.  
  1087. function FMCGetPageX( winNode, e )
  1088. {
  1089.     var pageX;
  1090.     
  1091.     if ( typeof( e.pageX ) != "undefined" )
  1092.     {
  1093.         pageX = e.pageX;
  1094.     }
  1095.     else if ( typeof( e.clientX ) != "undefined" )
  1096.     {
  1097.         pageX = e.clientX + FMCGetScrollLeft( winNode );
  1098.     }
  1099.     
  1100.     return pageX;
  1101. }
  1102.  
  1103. function FMCGetPageY( winNode, e )
  1104. {
  1105.     var pageY;
  1106.     
  1107.     if ( typeof( e.pageY ) != "undefined" )
  1108.     {
  1109.         pageY = e.pageY;
  1110.     }
  1111.     else if ( typeof( e.clientY ) != "undefined" )
  1112.     {
  1113.         pageY = e.clientY + FMCGetScrollTop( winNode );
  1114.     }
  1115.     
  1116.     return pageY;
  1117. }
  1118.  
  1119. function FMCGetMouseXRelativeTo( winNode, e, el )
  1120. {
  1121.     var mouseX    = FMCGetPageX( winNode, e, el );
  1122.     var elX        = FMCGetPosition( el )[1];
  1123.     var x        = mouseX - elX;
  1124.  
  1125.     return x;
  1126. }
  1127.  
  1128. function FMCGetMouseYRelativeTo( winNode, e, el )
  1129. {
  1130.     var mouseY    = FMCGetPageY( winNode, e, el );
  1131.     var elY        = FMCGetPosition( el )[0];
  1132.     var y        = mouseY - elY;
  1133.  
  1134.     return y;
  1135. }
  1136.  
  1137. function FMCGetPosition( node )
  1138. {
  1139.     var topPos    = 0;
  1140.     var leftPos    = 0;
  1141.     
  1142.     if ( node.offsetParent )
  1143.     {
  1144.         topPos = node.offsetTop;
  1145.         leftPos = node.offsetLeft;
  1146.         
  1147.         while ( node = node.offsetParent )
  1148.         {
  1149.             topPos += node.offsetTop;
  1150.             leftPos += node.offsetLeft;
  1151.         }
  1152.     }
  1153.     
  1154.     return [topPos, leftPos];
  1155. }
  1156.  
  1157. function FMCScrollToVisible( win, node )
  1158. {
  1159.     var offset            = 0;
  1160.     
  1161.     if ( typeof( window.innerWidth ) != "undefined" && !FMCIsSafari() )
  1162.     {
  1163.         offset = 19;
  1164.     }
  1165.     
  1166.     var scrollTop        = FMCGetScrollTop( win );
  1167.     var scrollBottom    = scrollTop + FMCGetClientHeight( win, false ) - offset;
  1168.     var scrollLeft        = FMCGetScrollLeft( win );
  1169.     var scrollRight        = scrollLeft + FMCGetClientWidth( win, false ) - offset;
  1170.     
  1171.     var nodePos            = FMCGetPosition( node );
  1172.     var nodeTop            = nodePos[0];
  1173.     var nodeLeft        = parseInt( node.style.textIndent ) + nodePos[1];
  1174.     var nodeHeight        = node.offsetHeight;
  1175.     var nodeWidth        = node.getElementsByTagName( "a" )[0].offsetWidth;
  1176.     
  1177.     if ( nodeTop < scrollTop )
  1178.     {
  1179.         FMCSetScrollTop( win, nodeTop );
  1180.     }
  1181.     else if ( nodeTop + nodeHeight > scrollBottom )
  1182.     {
  1183.         FMCSetScrollTop( win, Math.min( nodeTop, nodeTop + nodeHeight - FMCGetClientHeight( win, false ) + offset ) );
  1184.     }
  1185.     
  1186.     if ( nodeLeft < scrollLeft )
  1187.     {
  1188.         FMCSetScrollLeft( win, nodeLeft );
  1189.     }
  1190.     else if ( nodeLeft + nodeWidth > scrollRight )
  1191.     {
  1192.         FMCSetScrollLeft( win, Math.min( nodeLeft, nodeLeft + nodeWidth - FMCGetClientWidth( win, false ) + offset ) );
  1193.     }
  1194. }
  1195.  
  1196. function FMCGetComputedStyle( node, style )
  1197. {
  1198.     var value   = null;
  1199.     
  1200.     if ( node.currentStyle )
  1201.     {
  1202.         value = node.currentStyle[style];
  1203.     }
  1204.     else if ( document.defaultView && document.defaultView.getComputedStyle )
  1205.     {
  1206.         var computedStyle    = document.defaultView.getComputedStyle( node, null );
  1207.         
  1208.         if ( computedStyle )
  1209.         {
  1210.             value = computedStyle[style];
  1211.         }
  1212.     }
  1213.     
  1214.     return value;
  1215. }
  1216.  
  1217. function FMCConvertToPx( doc, str, dimension, defaultValue )
  1218. {
  1219.     if ( !str || str.charAt( 0 ) == "-" )
  1220.     {
  1221.         return defaultValue;
  1222.     }
  1223.     
  1224.     if ( str.charAt( str.length - 1 ) == "\%" )
  1225.     {
  1226.         switch (dimension)
  1227.         {
  1228.             case "Width":
  1229.                 return parseInt( str ) * screen.width / 100;
  1230.                 
  1231.                 break;
  1232.             case "Height":
  1233.                 return parseInt( str ) * screen.height / 100;
  1234.                 
  1235.                 break;
  1236.         }
  1237.     }
  1238.     else
  1239.     {
  1240.         if ( parseInt( str ).toString() == str )
  1241.         {
  1242.             str += "px";
  1243.         }
  1244.     }
  1245.     
  1246.     try
  1247.     {
  1248.         var div    = doc.createElement( "div" );
  1249.     }
  1250.     catch ( err )
  1251.     {
  1252.         return defaultValue;
  1253.     }
  1254.     
  1255.     doc.body.appendChild( div );
  1256.     
  1257.     var value    = defaultValue;
  1258.     
  1259.     try
  1260.     {
  1261.         div.style.width = str;
  1262.         
  1263.         if ( div.currentStyle )
  1264.         {
  1265.             value = div.offsetWidth;
  1266.         }
  1267.         else if ( document.defaultView && document.defaultView.getComputedStyle )
  1268.         {
  1269.             value = parseInt( FMCGetComputedStyle( div, "width" ) );
  1270.         }
  1271.     }
  1272.     catch ( err )
  1273.     {
  1274.     }
  1275.     
  1276.     doc.body.removeChild( div );
  1277.     
  1278.     return value;
  1279. }
  1280.  
  1281. function FMCGetOpacity( el )
  1282. {
  1283.     var opacity    = 0;
  1284.     
  1285.     if ( el.filters )
  1286.     {
  1287.         opacity = parseInt( el.style.filter.substring( 17, el.style.filter.length - 2 ) );
  1288.     }
  1289.     else if ( el.style.MozOpacity != null )
  1290.     {
  1291.         opacity = parseFloat( el.style.MozOpacity ) * 100;
  1292.     }
  1293.     
  1294.     return opacity;
  1295. }
  1296.  
  1297. function FMCSetOpacity( el, opacityPercent )
  1298. {
  1299.     if ( el.filters )
  1300.     {
  1301.         el.style.filter = "alpha( opacity = " + opacityPercent + " )";
  1302.     }
  1303.     else if ( el.style.MozOpacity != null )
  1304.     {
  1305.         el.style.MozOpacity = opacityPercent / 100;
  1306.     }
  1307. }
  1308.  
  1309. function FMCToggleDisplay( el )
  1310. {
  1311.     if ( el.style.display == "none" )
  1312.     {
  1313.         el.style.display = "";
  1314.     }
  1315.     else
  1316.     {
  1317.         el.style.display = "none";
  1318.     }
  1319. }
  1320.  
  1321. function FMCIsChildNode( childNode, parentNode )
  1322. {
  1323.     var    doc    = parentNode.ownerDocument;
  1324.     
  1325.     if ( childNode == null )
  1326.     {
  1327.         return null;
  1328.     }
  1329.     
  1330.     for ( var currNode = childNode; ; currNode = currNode.parentNode )
  1331.     {
  1332.         if ( currNode == parentNode )
  1333.         {
  1334.             return true;
  1335.         }
  1336.         
  1337.         if ( currNode == doc.body )
  1338.         {
  1339.             return false;
  1340.         }
  1341.     }
  1342. }
  1343.  
  1344. function FMCStripCssUrl( url )
  1345. {
  1346.     if ( !url )
  1347.     {
  1348.         return null;
  1349.     }
  1350.     
  1351.     var regex    = /url\(\s*(['\"]?)([^'\"\s]*)\1\s*\)/;
  1352.     var match    = regex.exec( url );
  1353.     
  1354.     if ( match )
  1355.     {
  1356.         return match[2];
  1357.     }
  1358.     
  1359.     return null;
  1360. }
  1361.  
  1362. function FMCCreateCssUrl( path )
  1363. {
  1364.     return "url(\"" + path + "\")";
  1365. }
  1366.  
  1367. function FMCGetPropertyValue( propertyNode, defaultValue )
  1368. {
  1369.     var propValue    = defaultValue;
  1370.     var valueNode    = propertyNode.firstChild;
  1371.     
  1372.     if ( valueNode )
  1373.     {
  1374.         propValue = valueNode.nodeValue;
  1375.     }
  1376.     
  1377.     return propValue;
  1378. }
  1379.  
  1380. function FMCParseInt( str, defaultValue )
  1381. {
  1382.     var num    = parseInt( str );
  1383.  
  1384.     if ( num.toString() == "NaN" )
  1385.     {
  1386.         num = defaultValue;
  1387.     }
  1388.     
  1389.     return num;
  1390. }
  1391.  
  1392. function FMCConvertBorderToPx( doc, value )
  1393. {
  1394.     var newValue    = "";
  1395.     var valueParts    = value.split( " " );
  1396.  
  1397.     for ( var i = 0; i < valueParts.length; i++ )
  1398.     {
  1399.         var currPart    = valueParts[i];
  1400.         
  1401.         if ( i == 1 )
  1402.         {
  1403.             currPart = FMCConvertToPx( doc, currPart, null, currPart );
  1404.             
  1405.             if ( parseInt( currPart ).toString() == currPart )
  1406.             {
  1407.                 currPart += "px";
  1408.             }
  1409.         }
  1410.  
  1411.         newValue += (((i > 0) ? " " : "") + currPart);
  1412.     }
  1413.     
  1414.     return newValue;
  1415. }
  1416.  
  1417. function FMCUnhide( win, node )
  1418. {
  1419.     for ( var currNode = node.parentNode; currNode.nodeName != "BODY"; currNode = currNode.parentNode )
  1420.     {
  1421.         if ( currNode.style.display == "none" )
  1422.         {
  1423.             var classRoot   = FMCContainsClassRoot( currNode.className, "MCExpandingBody", "MCDropDownBody", "MCTextPopupBody" );
  1424.             
  1425.             if ( classRoot == "MCExpandingBody" )
  1426.             {
  1427.                 win.FMCExpand( currNode.parentNode.getElementsByTagName("a")[0] );
  1428.             }
  1429.             else if ( classRoot == "MCDropDownBody" )
  1430.             {
  1431.                 var dropDownBodyID  = currNode.id.substring( "MCDropDownBody".length + 1, currNode.id.length );
  1432.                 var aNodes          = currNode.parentNode.getElementsByTagName( "a" );
  1433.                 
  1434.                 for ( var i = 0; i < aNodes.length; i++ )
  1435.                 {
  1436.                     var aNode   = aNodes[i];
  1437.                     
  1438.                     if ( aNode.id.substring( "MCDropDownHotSpot".length + 1, aNode.id.length ) == dropDownBodyID )
  1439.                     {
  1440.                         win.FMCDropDown( aNode );
  1441.                     }
  1442.                 }
  1443.             }
  1444.             else if ( FMCGetMCAttribute( currNode, "MadCap:targetName" ) )
  1445.             {
  1446.                 var targetName      = FMCGetMCAttribute( currNode, "MadCap:targetName" );
  1447.                 var togglerNodes    = FMCGetElementsByClassRoot( win.document.body, "MCToggler" );
  1448.                 
  1449.                 for ( var i = 0; i < togglerNodes.length; i++ )
  1450.                 {
  1451.                     var targets = FMCGetMCAttribute( togglerNodes[i], "MadCap:targets" ).split( ";" );
  1452.                     var found   = false;
  1453.                     
  1454.                     for ( var j = 0; j < targets.length; j++ )
  1455.                     {
  1456.                         if ( targets[j] == targetName )
  1457.                         {
  1458.                             found = true;
  1459.                             
  1460.                             break;
  1461.                         }
  1462.                     }
  1463.                     
  1464.                     if ( !found )
  1465.                     {
  1466.                         continue;
  1467.                     }
  1468.                     
  1469.                     win.FMCToggler( togglerNodes[i] );
  1470.                     
  1471.                     break;
  1472.                 }
  1473.             }
  1474.             else if ( classRoot == "MCTextPopupBody" )
  1475.             {
  1476.                 continue;
  1477.             }
  1478.             else
  1479.             {
  1480.                 currNode.style.display = "";
  1481.             }
  1482.         }
  1483.     }
  1484. }
  1485.  
  1486. function StartLoading( win, parentElement, loadingLabel, loadingAltText, fadeElement )
  1487. {
  1488.     if ( !win.MCLoadingCount )
  1489.     {
  1490.         win.MCLoadingCount = 0;
  1491.     }
  1492.     
  1493.     win.MCLoadingCount++;
  1494.     
  1495.     if ( win.MCLoadingCount > 1 )
  1496.     {
  1497.         return;
  1498.     }
  1499.     
  1500.     //
  1501.     
  1502.     if ( fadeElement )
  1503.     {
  1504.         // IE bug: This causes the tab outline not to show and also causes the TOC entry fonts to look bold.
  1505.         //    if ( fadeElement.filters )
  1506.         //    {
  1507.         //        fadeElement.style.filter = "alpha( opacity = 10 )";
  1508.         //    }
  1509.         /*else*/ if ( fadeElement.style.MozOpacity != null )
  1510.         {
  1511.             fadeElement.style.MozOpacity = "0.1";
  1512.         }
  1513.     }
  1514.  
  1515.     var span        = win.document.createElement( "span" );
  1516.     var img            = win.document.createElement( "img" );
  1517.     var midPointX    = FMCGetScrollLeft( win ) + FMCGetClientWidth( win, false ) / 2;
  1518.     var spacing        = 3;
  1519.  
  1520.     parentElement.appendChild( span );
  1521.  
  1522.     span.id = "LoadingText";
  1523.     span.appendChild( win.document.createTextNode( loadingLabel ) );
  1524.     span.style.fontFamily = "Tahoma, Sans-Serif";
  1525.     span.style.fontSize = "9px";
  1526.     span.style.fontWeight = "bold";
  1527.     span.style.position = "absolute";
  1528.     span.style.left = (midPointX - (span.offsetWidth / 2)) + "px";
  1529.  
  1530.     var rootFrame    = FMCGetRootFrame();
  1531.     
  1532.     img.id = "LoadingImage";
  1533.     img.src = rootFrame.gRootFolder + MCGlobals.SkinTemplateFolder + "Images/Loading.gif";
  1534.     img.alt = loadingAltText;
  1535.     img.style.width = "70px";
  1536.     img.style.height = "13px";
  1537.     img.style.position = "absolute";
  1538.     img.style.left = (midPointX - (70/2)) + "px";
  1539.  
  1540.     var totalHeight    = span.offsetHeight + spacing + parseInt( img.style.height );
  1541.     var spanTop        = (FMCGetScrollTop( win ) + (FMCGetClientHeight( win, false ) - totalHeight)) / 2;
  1542.  
  1543.     span.style.top = spanTop + "px";
  1544.     img.style.top = spanTop + span.offsetHeight + spacing + "px";
  1545.  
  1546.     parentElement.appendChild( img );
  1547. }
  1548.  
  1549. function EndLoading( win, fadeElement )
  1550. {
  1551.     win.MCLoadingCount--;
  1552.     
  1553.     if ( win.MCLoadingCount > 0 )
  1554.     {
  1555.         return;
  1556.     }
  1557.     
  1558.     //
  1559.     
  1560.     var span    = win.document.getElementById( "LoadingText" );
  1561.     var img        = win.document.getElementById( "LoadingImage" );
  1562.  
  1563.     span.parentNode.removeChild( span );
  1564.     img.parentNode.removeChild( img );
  1565.  
  1566.     if ( fadeElement )
  1567.     {
  1568.         // IE bug: This causes the tab outline not to show and also causes the TOC entry fonts to look bold.
  1569.         //    if ( fadeElement.filters )
  1570.         //    {
  1571.         //        fadeElement.style.filter = "alpha( opacity = 100 )";
  1572.         //    }
  1573.         /*else*/ if ( fadeElement.style.MozOpacity != null )
  1574.         {
  1575.             fadeElement.style.MozOpacity = "1.0";
  1576.         }
  1577.     }
  1578. }
  1579.  
  1580. var gCallbacks        = new Array();
  1581. var gCallbackArgs    = new Array();
  1582.  
  1583. var MCEventType    = new Object();
  1584.  
  1585. MCEventType.OnLoad    = 0;
  1586. MCEventType.OnInit    = 1;
  1587. MCEventType.OnReady    = 2;
  1588.  
  1589. function FMCRegisterCallback( frameName, eventType, CallbackFunc, callbackArgs )
  1590. {
  1591.     var numCallbacks    = gCallbacks.length;
  1592.     var funcName        = "FMCCheck" + frameName;
  1593.     
  1594.     switch ( eventType )
  1595.     {
  1596.         case MCEventType.OnLoad:
  1597.             funcName = funcName + "Loaded";
  1598.             
  1599.             break;
  1600.         
  1601.         case MCEventType.OnInit:
  1602.             funcName = funcName + "Initialized";
  1603.             
  1604.             break;
  1605.             
  1606.         case MCEventType.OnReady:
  1607.             funcName = funcName + "Ready";
  1608.             
  1609.             break;
  1610.     }
  1611.  
  1612.     gCallbacks[numCallbacks] = CallbackFunc;
  1613.     gCallbackArgs[numCallbacks] = callbackArgs;
  1614.     
  1615.     setTimeout( funcName + "( " + numCallbacks + " );", 1 );
  1616. }
  1617.  
  1618. function FMCCheckMCGlobalsInitialized( index )
  1619. {
  1620.     if ( MCGlobals.Initialized )
  1621.     {
  1622.         gCallbacks[index]( gCallbackArgs[index] );
  1623.     }
  1624.     else
  1625.     {
  1626.         setTimeout( "FMCCheckMCGlobalsInitialized( " + index + " );", 1 );
  1627.     }
  1628. }
  1629.  
  1630. function FMCCheckRootReady( index )
  1631. {
  1632.     if ( MCGlobals.RootFrame.gReady )
  1633.     {
  1634.         gCallbacks[index]( gCallbackArgs[index] );
  1635.     }
  1636.     else
  1637.     {
  1638.         setTimeout( "FMCCheckRootReady( " + index + " );", 1 );
  1639.     }
  1640. }
  1641.  
  1642. function FMCCheckRootLoaded( index )
  1643. {
  1644.     if ( MCGlobals.RootFrame.gLoaded )
  1645.     {
  1646.         gCallbacks[index]( gCallbackArgs[index] );
  1647.     }
  1648.     else
  1649.     {
  1650.         setTimeout( "FMCCheckRootLoaded( " + index + " );", 1 );
  1651.     }
  1652. }
  1653.  
  1654. function FMCCheckTOCInitialized( index )
  1655. {
  1656.     if ( MCGlobals.NavigationFrame.frames["toc"].gInit )
  1657.     {
  1658.         gCallbacks[index]( gCallbackArgs[index] );
  1659.     }
  1660.     else
  1661.     {
  1662.         setTimeout( "FMCCheckTOCInitialized( " + index + " );", 1 );
  1663.     }
  1664. }
  1665.  
  1666. function FMCCheckSearchInitialized( index )
  1667. {
  1668.     if ( MCGlobals.NavigationFrame.frames["search"].gInit )
  1669.     {
  1670.         gCallbacks[index]( gCallbackArgs[index] );
  1671.     }
  1672.     else
  1673.     {
  1674.         setTimeout( "FMCCheckSearchInitialized( " + index + " );", 1 );
  1675.     }
  1676. }
  1677.  
  1678. function FMCCheckTopicCommentsLoaded( index )
  1679. {
  1680.     if ( MCGlobals.TopicCommentsFrame.gLoaded )
  1681.     {
  1682.         gCallbacks[index]( gCallbackArgs[index] );
  1683.     }
  1684.     else
  1685.     {
  1686.         setTimeout( "FMCCheckTopicCommentsLoaded( " + index + " );", 1 );
  1687.     }
  1688. }
  1689.  
  1690. function FMCCheckTopicCommentsInitialized( index )
  1691. {
  1692.     if ( MCGlobals.TopicCommentsFrame.gInit )
  1693.     {
  1694.         gCallbacks[index]( gCallbackArgs[index] );
  1695.     }
  1696.     else
  1697.     {
  1698.         setTimeout( "FMCCheckTopicCommentsInitialized( " + index + " );", 1 );
  1699.     }
  1700. }
  1701.  
  1702. function FMCCheckBodyCommentsLoaded( index )
  1703. {
  1704.     if ( MCGlobals.BodyCommentsFrame.gLoaded )
  1705.     {
  1706.         gCallbacks[index]( gCallbackArgs[index] );
  1707.     }
  1708.     else
  1709.     {
  1710.         setTimeout( "FMCCheckBodyCommentsLoaded( " + index + " );", 1 );
  1711.     }
  1712. }
  1713.  
  1714. function FMCCheckBodyCommentsInitialized( index )
  1715. {
  1716.     if ( MCGlobals.BodyCommentsFrame.gInit )
  1717.     {
  1718.         gCallbacks[index]( gCallbackArgs[index] );
  1719.     }
  1720.     else
  1721.     {
  1722.         setTimeout( "FMCCheckBodyCommentsInitialized( " + index + " );", 1 );
  1723.     }
  1724. }
  1725.  
  1726. function FMCCheckToolbarInitialized( index )
  1727. {
  1728.     if ( MCGlobals.ToolbarFrame.gInit )
  1729.     {
  1730.         gCallbacks[index]( gCallbackArgs[index] );
  1731.     }
  1732.     else
  1733.     {
  1734.         setTimeout( "FMCCheckToolbarInitialized( " + index + " );", 1 );
  1735.     }
  1736. }
  1737.  
  1738. function FMCCheckNavigationReady( index )
  1739. {
  1740.     if ( MCGlobals.NavigationFrame.gReady )
  1741.     {
  1742.         gCallbacks[index]( gCallbackArgs[index] );
  1743.     }
  1744.     else
  1745.     {
  1746.         setTimeout( "FMCCheckNavigationReady( " + index + " );", 1 );
  1747.     }
  1748. }
  1749.  
  1750. function FMCCheckNavigationLoaded( index )
  1751. {
  1752.     if ( MCGlobals.NavigationFrame.gLoaded )
  1753.     {
  1754.         gCallbacks[index]( gCallbackArgs[index] );
  1755.     }
  1756.     else
  1757.     {
  1758.         setTimeout( "FMCCheckNavigationLoaded( " + index + " );", 1 );
  1759.     }
  1760. }
  1761.  
  1762. function FMCCheckBodyReady( index )
  1763. {
  1764.     if ( typeof( MCGlobals.BodyFrame.gReady ) == "undefined" || MCGlobals.BodyFrame.gReady )
  1765.     {
  1766.         gCallbacks[index]( gCallbackArgs[index] );
  1767.     }
  1768.     else
  1769.     {
  1770.         setTimeout( "FMCCheckBodyReady( " + index + " );", 1 );
  1771.     }
  1772. }
  1773.  
  1774. function FMCCheckBodyLoaded( index )
  1775. {
  1776.     if ( MCGlobals.BodyFrame.gLoaded )
  1777.     {
  1778.         gCallbacks[index]( gCallbackArgs[index] );
  1779.     }
  1780.     else
  1781.     {
  1782.         setTimeout( "FMCCheckBodyLoaded( " + index + " );", 1 );
  1783.     }
  1784. }
  1785.  
  1786. function FMCCheckPersistenceInitialized( index )
  1787. {
  1788.     if ( MCGlobals.PersistenceFrame.gInit )
  1789.     {
  1790.         gCallbacks[index]( gCallbackArgs[index] );
  1791.     }
  1792.     else
  1793.     {
  1794.         setTimeout( "FMCCheckPersistenceInitialized( " + index + " );", 1 );
  1795.     }
  1796. }
  1797.  
  1798. function FMCSortStringArray( stringArray )
  1799. {
  1800.     stringArray.sort( FMCCompareStrings );
  1801. }
  1802.  
  1803. function FMCCompareStrings( a, b )
  1804. {
  1805.     var ret;
  1806.  
  1807.     if ( a.toLowerCase() < b.toLowerCase() )
  1808.     {
  1809.         ret = -1;
  1810.     }
  1811.     else if ( a.toLowerCase() == b.toLowerCase() )
  1812.     {
  1813.         ret = 0;
  1814.     }
  1815.     else if ( a.toLowerCase() > b.toLowerCase() )
  1816.     {
  1817.         ret = 1;
  1818.     }
  1819.  
  1820.     return ret;
  1821. }
  1822.  
  1823. function FMCSetCookie( name, value, days )
  1824. {
  1825.     if ( window != MCGlobals.NavigationFrame )
  1826.     {
  1827.         MCGlobals.NavigationFrame.FMCSetCookie( name, value, days );
  1828.         
  1829.         return;
  1830.     }
  1831.     
  1832.     value = encodeURI( value );
  1833.     
  1834.     if ( days )
  1835.     {
  1836.         var date    = new Date();
  1837.         
  1838.         date.setTime( date.getTime() + (1000 * 60 * 60 * 24 * days) );
  1839.         
  1840.         var expires    = "; expires=" + date.toGMTString();
  1841.     }
  1842.     else
  1843.     {
  1844.         var expires    = "";
  1845.     }
  1846.  
  1847.     var rootFrame    = FMCGetRootFrame();
  1848.     var navFrame    = rootFrame.frames["navigation"];
  1849.     var path        = FMCGetPathnameFolder( navFrame.document.location );
  1850.  
  1851.     //navFrame.document.cookie = name + "=" + value + expires + ";" + " path=" + path + ";";
  1852.     navFrame.document.cookie = name + "=" + value + expires + ";";
  1853. }
  1854.  
  1855. function FMCReadCookie( name )
  1856. {
  1857.     var value        = null;
  1858.     var nameEq        = name + "=";
  1859.     var rootFrame    = FMCGetRootFrame();
  1860.     var navFrame    = rootFrame.frames["navigation"];
  1861.     var cookies        = navFrame.document.cookie.split( ";" );
  1862.  
  1863.     for ( var i = 0; i < cookies.length; i++ )
  1864.     {
  1865.         var cookie    = cookies[i];
  1866.         
  1867.         cookie = FMCTrim( cookie );
  1868.         
  1869.         if ( cookie.indexOf( nameEq ) == 0 )
  1870.         {
  1871.             value = cookie.substring( nameEq.length, cookie.length );
  1872.             value = decodeURI( value );
  1873.             
  1874.             break;
  1875.         }
  1876.     }
  1877.  
  1878.     return value;
  1879. }
  1880.  
  1881. function FMCRemoveCookie( name )
  1882. {
  1883.     FMCSetCookie( name, "", -1 );
  1884. }
  1885.  
  1886. function FMCLoadUserData( name )
  1887. {
  1888.     var persistFrame    = MCGlobals.PersistenceFrame;
  1889.     var persistDiv        = persistFrame.document.getElementById( "Persist" );
  1890.     
  1891.     persistDiv.load( "MCXMLStore" );
  1892.     
  1893.     var value    = persistDiv.getAttribute( name );
  1894.     
  1895.     return value;
  1896. }
  1897.  
  1898. function FMCSaveUserData( name, value )
  1899. {
  1900.     var persistFrame    = MCGlobals.PersistenceFrame;
  1901.     var persistDiv        = persistFrame.document.getElementById( "Persist" );
  1902.     
  1903.     persistDiv.setAttribute( name, value );
  1904.     persistDiv.save( "MCXMLStore" );
  1905. }
  1906.  
  1907. function FMCRemoveUserData( name )
  1908. {
  1909.     var persistFrame    = MCGlobals.PersistenceFrame;
  1910.     var persistDiv        = persistFrame.document.getElementById( "Persist" );
  1911.     
  1912.     persistDiv.removeAttribute( name );
  1913.     persistDiv.save( "MCXMLStore" );
  1914. }
  1915.  
  1916. function FMCInsertOpacitySheet( winNode, color )
  1917. {
  1918.     var div        = winNode.document.createElement( "div" );
  1919.     var style    = div.style;
  1920.     
  1921.     div.id = "MCOpacitySheet";
  1922.     style.position = "absolute";
  1923.     style.top = FMCGetScrollTop( winNode ) + "px";
  1924.     style.left = FMCGetScrollLeft( winNode ) + "px";
  1925.     style.width = FMCGetClientWidth( winNode, false ) + "px";
  1926.     style.height = FMCGetClientHeight( winNode, false ) + "px";
  1927.     style.backgroundColor = color;
  1928.     style.zIndex = "100";
  1929.     
  1930.     winNode.document.body.appendChild( div );
  1931.     
  1932.     FMCSetOpacity( div, 75 );
  1933. }
  1934.  
  1935. function FMCRemoveOpacitySheet( winNode )
  1936. {
  1937.     var div    = winNode.document.getElementById( "MCOpacitySheet" );
  1938.     
  1939.     if ( !div )
  1940.     {
  1941.         return;
  1942.     }
  1943.     
  1944.     div.parentNode.removeChild( div );
  1945. }
  1946.  
  1947. function FMCSetupButtonFromStylesheet( tr, styleName, styleClassName, defaultOutPath, defaultOverPath, defaultSelectedPath, defaultWidth, defaultHeight, defaultTooltip, defaultLabel, OnClickHandler )
  1948. {
  1949.     var td                    = document.createElement( "td" );
  1950.     var outImagePath        = CMCFlareStylesheet.LookupValue( styleName, styleClassName, "Icon", null );
  1951.     var overImagePath        = CMCFlareStylesheet.LookupValue( styleName, styleClassName, "HoverIcon", null );
  1952.     var selectedImagePath    = CMCFlareStylesheet.LookupValue( styleName, styleClassName, "PressedIcon", null );
  1953.     
  1954.     if ( outImagePath == null )
  1955.     {
  1956.         outImagePath = defaultOutPath;
  1957.     }
  1958.     else
  1959.     {
  1960.         outImagePath = FMCStripCssUrl( outImagePath );
  1961.         outImagePath = MCGlobals.RootFolder + FMCGetSkinFolder() + outImagePath;
  1962.     }
  1963.     
  1964.     if ( overImagePath == null )
  1965.     {
  1966.         overImagePath = defaultOverPath;
  1967.     }
  1968.     else
  1969.     {
  1970.         overImagePath = FMCStripCssUrl( overImagePath );
  1971.         overImagePath = MCGlobals.RootFolder + FMCGetSkinFolder() + overImagePath;
  1972.     }
  1973.     
  1974.     if ( selectedImagePath == null )
  1975.     {
  1976.         selectedImagePath = defaultSelectedPath;
  1977.     }
  1978.     else
  1979.     {
  1980.         selectedImagePath = FMCStripCssUrl( selectedImagePath );
  1981.         selectedImagePath = MCGlobals.RootFolder + FMCGetSkinFolder() + selectedImagePath;
  1982.     }
  1983.  
  1984.     tr.appendChild( td );
  1985.     
  1986.     var title    = CMCFlareStylesheet.LookupValue( styleName, styleClassName, "Tooltip", defaultTooltip );
  1987.     var label    = CMCFlareStylesheet.LookupValue( styleName, styleClassName, "Label", defaultLabel );
  1988.     var width    = CMCFlareStylesheet.GetResourceProperty( outImagePath, "Width", defaultWidth );
  1989.     var height    = CMCFlareStylesheet.GetResourceProperty( outImagePath, "Height", defaultHeight );
  1990.     
  1991.     MakeButton( td, title, outImagePath, overImagePath, selectedImagePath, width, height, label );
  1992.     td.firstChild.onclick = OnClickHandler;
  1993. }
  1994.  
  1995. //
  1996. //    End helper functions
  1997. //
  1998.  
  1999. //
  2000. //    Class CMCXmlParser
  2001. //
  2002.  
  2003. function CMCXmlParser( args, LoadFunc )
  2004. {
  2005.     // Private member variables and functions
  2006.     
  2007.     var mSelf        = this;
  2008.     this.mXmlDoc    = null;
  2009.     this.mXmlHttp    = null;
  2010.     this.mArgs        = args;
  2011.     this.mLoadFunc    = LoadFunc;
  2012.     
  2013.     this.OnreadystatechangeLocal    = function()
  2014.     {
  2015.         if ( mSelf.mXmlDoc.readyState == 4 )
  2016.         {
  2017.             mSelf.mLoadFunc( mSelf.mXmlDoc, mSelf.mArgs );
  2018.         }
  2019.     };
  2020.     
  2021.     this.OnreadystatechangeRemote    = function()
  2022.     {
  2023.         if ( mSelf.mXmlHttp.readyState == 4 )
  2024.         {
  2025.             mSelf.mLoadFunc( mSelf.mXmlHttp.responseXML, mSelf.mArgs );
  2026.         }
  2027.     };
  2028. }
  2029.  
  2030. CMCXmlParser.prototype.LoadLocal    = function( xmlFile, async )
  2031. {
  2032.     if ( window.ActiveXObject )
  2033.     {
  2034.         this.mXmlDoc = new ActiveXObject( "Microsoft.XMLDOM" );
  2035.         this.mXmlDoc.async = async;
  2036.         
  2037.         if ( this.mLoadFunc )
  2038.         {
  2039.             this.mXmlDoc.onreadystatechange = this.OnreadystatechangeLocal;
  2040.         }
  2041.         
  2042.         try
  2043.         {
  2044.             if ( !this.mXmlDoc.load( xmlFile ) )
  2045.             {
  2046.                 this.mXmlDoc = null;
  2047.             }
  2048.         }
  2049.         catch ( err )
  2050.         {
  2051.             this.mXmlDoc = null;
  2052.         }
  2053.     }
  2054.     else if ( window.XMLHttpRequest )
  2055.     {
  2056.         this.LoadRemote( xmlFile, async ); // window.XMLHttpRequest also works on local files
  2057.     }
  2058.  
  2059.     return this.mXmlDoc;
  2060. };
  2061.  
  2062. CMCXmlParser.prototype.LoadRemote    = function( xmlFile, async )
  2063. {
  2064.     if ( window.ActiveXObject )
  2065.     {
  2066.         this.mXmlHttp = new ActiveXObject( "Msxml2.XMLHTTP" );
  2067.     }
  2068.     else if ( window.XMLHttpRequest )
  2069.     {
  2070.         xmlFile = xmlFile.replace( /;/g, "%3B" );   // For Safari
  2071.         this.mXmlHttp = new XMLHttpRequest();
  2072.     }
  2073.     
  2074.     if ( this.mLoadFunc )
  2075.     {
  2076.         this.mXmlHttp.onreadystatechange = this.OnreadystatechangeRemote;
  2077.     }
  2078.     
  2079.     this.mXmlHttp.open( "GET", xmlFile, async );
  2080.     
  2081.     try
  2082.     {
  2083.         this.mXmlHttp.send( null );
  2084.     }
  2085.     catch ( err )
  2086.     {
  2087.         this.mXmlHttp.abort();
  2088.     }
  2089.     
  2090.     if ( !async && (this.mXmlHttp.status == 0 || this.mXmlHttp.status == 200) )
  2091.     {
  2092.         this.mXmlDoc = this.mXmlHttp.responseXML;
  2093.     }
  2094.     
  2095.     return this.mXmlDoc;
  2096. };
  2097.  
  2098. // Public member functions
  2099.  
  2100. CMCXmlParser.prototype.Load    = function( xmlFile, async )
  2101. {
  2102.     var xmlDoc            = null;
  2103.     var protocolType    = document.location.protocol;
  2104.     
  2105.     if ( protocolType == "file:" || protocolType == "mk:" )
  2106.     {
  2107.         xmlDoc = this.LoadLocal( xmlFile, async );
  2108.     }
  2109.     else if ( protocolType == "http:" || protocolType == "https:" )
  2110.     {
  2111.         xmlDoc = this.LoadRemote( xmlFile, async );
  2112.     }
  2113.     
  2114.     return xmlDoc;
  2115. };
  2116.  
  2117. // Static member functions
  2118.  
  2119. CMCXmlParser.GetXmlDoc    = function( xmlFile, async, LoadFunc, args )
  2120. {
  2121.     var xmlParser    = new CMCXmlParser( args, LoadFunc );
  2122.     var xmlDoc        = xmlParser.Load( xmlFile, async );
  2123.     
  2124.     return xmlDoc;
  2125. }
  2126.  
  2127. CMCXmlParser.LoadXmlString    = function( xmlString )
  2128. {
  2129.     var xmlDoc    = null;
  2130.     
  2131.     if ( window.ActiveXObject )
  2132.     {
  2133.         xmlDoc = new ActiveXObject( "Microsoft.XMLDOM" );
  2134.         xmlDoc.async = false;
  2135.         xmlDoc.loadXML( xmlString );
  2136.     }
  2137.     else if ( DOMParser )
  2138.     {
  2139.         var parser    = new DOMParser();
  2140.         
  2141.         xmlDoc = parser.parseFromString( xmlString, "text/xml" );
  2142.     }
  2143.     
  2144.     return xmlDoc;
  2145. }
  2146.  
  2147. CMCXmlParser.CallWebService    = function( webServiceUrl, async, onCompleteFunc, onCompleteArgs )
  2148. {
  2149.     var xmlParser    = new CMCXmlParser( onCompleteArgs, onCompleteFunc );
  2150.     var xmlDoc        = xmlParser.LoadRemote( webServiceUrl, async );
  2151.     
  2152.     return xmlDoc;
  2153. }
  2154.  
  2155. //
  2156. //    End class CMCXmlParser
  2157. //
  2158.  
  2159. //
  2160. //    Class CMCFlareStylesheet
  2161. //
  2162.  
  2163. var CMCFlareStylesheet    = new function()
  2164. {
  2165.     // Private member variables
  2166.  
  2167.     var mInitialized            = false;
  2168.     var mXmlDoc                    = null;
  2169.     var mInitializedResources    = false;
  2170.     var mResourceMap            = null;
  2171.     
  2172.     // Private methods
  2173.     
  2174.     function Init()
  2175.     {
  2176.         mXmlDoc = CMCXmlParser.GetXmlDoc( MCGlobals.RootFolder + FMCGetSkinFolder() + "Stylesheet.xml", false, null, null );
  2177.         
  2178.         mInitialized = true;
  2179.     }
  2180.     
  2181.     function InitializeResources()
  2182.     {
  2183.         mInitializedResources = true;
  2184.         mResourceMap = new CMCDictionary();
  2185.         
  2186.         var styleDoc        = CMCXmlParser.GetXmlDoc( MCGlobals.RootFolder + FMCGetSkinFolder() + "Stylesheet.xml", false, null, null );
  2187.         var resourcesInfos    = styleDoc.getElementsByTagName( "ResourcesInfo" );
  2188.  
  2189.         if ( resourcesInfos.length > 0 )
  2190.         {
  2191.             var resources    = resourcesInfos[0].getElementsByTagName( "Resource" );
  2192.  
  2193.             for ( var i = 0; i < resources.length; i++ )
  2194.             {
  2195.                 var resource    = resources[i];
  2196.                 var properties    = new CMCDictionary();
  2197.                 var name        = resource.getAttribute( "Name" );
  2198.                 
  2199.                 if ( !name ) { continue; }
  2200.  
  2201.                 for ( var j = 0; j < resource.attributes.length; j++ )
  2202.                 {
  2203.                     var attribute    = resource.attributes[j];
  2204.                     
  2205.                     properties.Add( attribute.nodeName.toLowerCase(), attribute.nodeValue.toLowerCase() );
  2206.                 }
  2207.  
  2208.                 mResourceMap.Add( name, properties );
  2209.             }
  2210.         }
  2211.     }
  2212.     
  2213.     // Public methods
  2214.     
  2215.     this.LookupValue    = function( styleName, styleClassName, propertyName, defaultValue )
  2216.     {
  2217.         if ( !mInitialized )
  2218.         {
  2219.             Init();
  2220.             
  2221.             if ( mXmlDoc == null )
  2222.             {
  2223.                 return defaultValue;
  2224.             }
  2225.         }
  2226.         
  2227.         var value                = defaultValue;
  2228.         var styleNodes            = mXmlDoc.getElementsByTagName( "Style" );
  2229.         var styleNodesLength    = styleNodes.length;
  2230.         var styleNode            = null;
  2231.         
  2232.         for ( var i = 0; i < styleNodesLength; i++ )
  2233.         {
  2234.             if ( styleNodes[i].getAttribute( "Name" ) == styleName )
  2235.             {
  2236.                 styleNode = styleNodes[i];
  2237.                 break;
  2238.             }
  2239.         }
  2240.         
  2241.         if ( styleNode == null )
  2242.         {
  2243.             return value;
  2244.         }
  2245.         
  2246.         var styleClassNodes            = styleNode.getElementsByTagName( "StyleClass" );
  2247.         var styleClassNodesLength    = styleClassNodes.length;
  2248.         var styleClassNode            = null;
  2249.         
  2250.         for ( var i = 0; i < styleClassNodesLength; i++ )
  2251.         {
  2252.             if ( styleClassNodes[i].getAttribute( "Name" ) == styleClassName )
  2253.             {
  2254.                 styleClassNode = styleClassNodes[i];
  2255.                 break;
  2256.             }
  2257.         }
  2258.         
  2259.         if ( styleClassNode == null )
  2260.         {
  2261.             return value;
  2262.         }
  2263.         
  2264.         var propertyNodes        = styleClassNode.getElementsByTagName( "Property" );
  2265.         var propertyNodesLength    = propertyNodes.length;
  2266.         var propertyNode        = null;
  2267.         
  2268.         for ( var i = 0; i < propertyNodesLength; i++ )
  2269.         {
  2270.             if ( propertyNodes[i].getAttribute( "Name" ) == propertyName )
  2271.             {
  2272.                 propertyNode = propertyNodes[i];
  2273.                 break;
  2274.             }
  2275.         }
  2276.         
  2277.         if ( propertyNode == null )
  2278.         {
  2279.             return value;
  2280.         }
  2281.         
  2282.         value = propertyNode.firstChild.nodeValue;
  2283.         value = FMCTrim( value );
  2284.         
  2285.         return value;
  2286.     };
  2287.     
  2288.     this.GetResourceProperty    = function( name, property, defaultValue )
  2289.     {
  2290.         if ( !mInitialized )
  2291.         {
  2292.             Init();
  2293.             
  2294.             if ( mXmlDoc == null )
  2295.             {
  2296.                 return defaultValue;
  2297.             }
  2298.         }
  2299.         
  2300.         if ( !mInitializedResources )
  2301.         {
  2302.             InitializeResources();
  2303.         }
  2304.         
  2305.         var properties    = mResourceMap.GetItem( name );
  2306.  
  2307.         if ( !properties )
  2308.         {
  2309.             return defaultValue;
  2310.         }
  2311.  
  2312.         var propValue    = properties.GetItem( property.toLowerCase() );
  2313.  
  2314.         if ( !propValue )
  2315.         {
  2316.             return defaultValue;
  2317.         }
  2318.  
  2319.         return propValue;
  2320.     };
  2321.     
  2322.     this.SetImageFromStylesheet    = function( img, styleName, styleClassName, propertyName, defaultValue, defaultWidth, defaultHeight )
  2323.     {
  2324.         var value    = this.LookupValue( styleName, styleClassName, propertyName, null );
  2325.         var imgSrc    = null;
  2326.         
  2327.         if ( value == null )
  2328.         {
  2329.             value = defaultValue;
  2330.             imgSrc = value;
  2331.         }
  2332.         else
  2333.         {
  2334.             value = FMCStripCssUrl( value );
  2335.             value = decodeURIComponent( value );
  2336.             value = escape( value );
  2337.             imgSrc = MCGlobals.RootFolder + FMCGetSkinFolder() + value;
  2338.         }
  2339.         
  2340.         img.src = imgSrc;
  2341.         img.style.width = this.GetResourceProperty( value, "Width", defaultWidth ) + "px";
  2342.         img.style.height = this.GetResourceProperty( value, "Height", defaultHeight ) + "px";
  2343.     };
  2344. }
  2345.  
  2346. //
  2347. //    End class CMCFlareStylesheet
  2348. //
  2349.  
  2350. //
  2351. //    Class CMCDictionary
  2352. //
  2353.  
  2354. function CMCDictionary()
  2355. {
  2356.     // Public properties
  2357.     
  2358.     this.mMap    = new Array();
  2359.     this.mKeys    = new Array();
  2360. }
  2361.  
  2362. CMCDictionary.prototype.GetItem    = function( key )
  2363. {
  2364.     var item    = this.mMap["_" + key];
  2365.  
  2366.     if ( typeof( item ) == "undefined" )
  2367.     {
  2368.         item = null;
  2369.     }
  2370.  
  2371.     return item;
  2372. };
  2373.  
  2374. CMCDictionary.prototype.GetKeys    = function()
  2375. {
  2376.     return this.mKeys;
  2377. };
  2378.  
  2379. CMCDictionary.prototype.Remove    = function( key )
  2380. {
  2381.     delete( this.mMap["_" + key] );
  2382.     delete( this.mKeys[key] );
  2383. };
  2384.  
  2385. CMCDictionary.prototype.Add    = function( key, value )
  2386. {
  2387.     this.mMap["_" + key] = value;
  2388.     this.mKeys[key] = true;
  2389. };
  2390.  
  2391. CMCDictionary.prototype.AddUnique    = function( key, value )
  2392. {
  2393.     var savedValue    = this.mKeys[key];
  2394.     
  2395.     if ( typeof( savedValue ) == "undefined" || !savedValue )
  2396.     {
  2397.         this.Add( key, value );
  2398.     }
  2399. };
  2400.  
  2401. //
  2402. //    End class CMCDictionary
  2403. //
  2404.  
  2405. //
  2406. //    DOM traversal functions
  2407. //
  2408.  
  2409. function FMCGetElementsByClassRoot( node, classRoot )
  2410. {
  2411.     var nodes   = new Array();
  2412.     var args    = new Array();
  2413.     
  2414.     args[0] = nodes;
  2415.     args[1] = classRoot;
  2416.     
  2417.     FMCTraverseDOM( "post", node, FMCGetByClassRoot, args );
  2418.                          
  2419.     return nodes;
  2420. }
  2421.  
  2422. function FMCGetByClassRoot( node, args )
  2423. {
  2424.     var nodes       = args[0];
  2425.     var classRoot   = args[1];
  2426.     
  2427.     if ( node.nodeType == 1 && FMCContainsClassRoot( node.className, classRoot ) )
  2428.     {
  2429.         nodes[nodes.length] = node;
  2430.     }
  2431. }
  2432.  
  2433. function FMCGetElementsByAttribute( node, attribute, value )
  2434. {
  2435.     var nodes   = new Array();
  2436.     var args    = new Array();
  2437.     
  2438.     args[0] = nodes;
  2439.     args[1] = attribute;
  2440.     args[2] = value;
  2441.     
  2442.     FMCTraverseDOM( "post", node, FMCGetByAttribute, args );
  2443.                          
  2444.     return nodes;
  2445. }
  2446.  
  2447. function FMCGetByAttribute( node, args )
  2448. {
  2449.     var nodes       = args[0];
  2450.     var attribute   = args[1];
  2451.     var value       = args[2];
  2452.     
  2453.     try
  2454.     {
  2455.         if ( node.nodeType == 1 && (FMCGetMCAttribute( node, attribute ) == value || (value == "*" && FMCGetMCAttribute( node, attribute ))) )
  2456.         {
  2457.             nodes[nodes.length] = node;
  2458.         }
  2459.     }
  2460.     catch( err )
  2461.     {
  2462.         node.setAttribute( attribute, null );
  2463.     }
  2464. }
  2465.  
  2466. function FMCTraverseDOM( type, root, Func, args )
  2467. {
  2468.     if ( type == "pre" )
  2469.     {
  2470.         Func( root, args );
  2471.     }
  2472.     
  2473.     if ( root.childNodes.length != 0 )
  2474.     {
  2475.         for ( var i = 0; i < root.childNodes.length; i++ )
  2476.         {
  2477.             FMCTraverseDOM( type, root.childNodes[i], Func, args );
  2478.         }
  2479.     }
  2480.     
  2481.     if ( type == "post" )
  2482.     {
  2483.         Func( root, args );
  2484.     }
  2485. }
  2486.  
  2487. //
  2488. //    End DOM traversal functions
  2489. //
  2490.  
  2491. //
  2492. //    Button effects
  2493. //
  2494.  
  2495. var gButton        = null;
  2496. var gTabIndex    = 1;
  2497.  
  2498. function MakeButton( td, title, outImagePath, overImagePath, selectedImagePath, width, height, text )
  2499. {
  2500.     var div    = document.createElement( "div" );
  2501.     
  2502.     div.tabIndex = gTabIndex++;
  2503.     
  2504.     title ? div.title = title : false;
  2505.     div.setAttribute( "MadCap:outImage", outImagePath );
  2506.     div.setAttribute( "MadCap:overImage", overImagePath );
  2507.     div.setAttribute( "MadCap:selectedImage", selectedImagePath );
  2508.     div.setAttribute( "MadCap:width", width );
  2509.     div.setAttribute( "MadCap:height", height );
  2510.     
  2511.     FMCPreloadImage( outImagePath );
  2512.     FMCPreloadImage( overImagePath );
  2513.     FMCPreloadImage( selectedImagePath );
  2514.     
  2515.     div.appendChild( document.createTextNode( text ) );
  2516.     td.appendChild( div );
  2517.     
  2518.     InitButton( div );
  2519. }
  2520.  
  2521. function InitButton( button )
  2522. {
  2523.     var width    = parseInt( FMCGetMCAttribute( button, "MadCap:width" ) ) + "px";
  2524.     var height    = parseInt( FMCGetMCAttribute( button, "MadCap:height" ) ) + "px";
  2525.     var image    = FMCGetMCAttribute( button, "MadCap:outImage" );
  2526.     
  2527.     if ( image != null )
  2528.     {
  2529.         if ( !image.StartsWith( "url", false ) || !image.EndsWith( ")", false ) )
  2530.         {
  2531.             image = FMCCreateCssUrl( image );
  2532.         }
  2533.  
  2534.         button.style.backgroundImage = image;
  2535.     }
  2536.     
  2537.     button.style.cursor = "default";
  2538.     button.style.width = width;
  2539.     button.style.height = height;
  2540.     button.onmouseover = ButtonOnOver;
  2541.     button.onmouseout = ButtonOnOut;
  2542.     button.onmousedown = ButtonOnDown;
  2543.  
  2544.     button.parentNode.style.width = width;
  2545.     button.parentNode.style.height = height;
  2546. }
  2547.  
  2548. function ButtonOnOver()
  2549. {
  2550.     var image    = FMCGetMCAttribute( this, "MadCap:overImage" );
  2551.     
  2552.     if ( !image.StartsWith( "url", false ) || !image.EndsWith( ")", false ) )
  2553.     {
  2554.         image = FMCCreateCssUrl( image );
  2555.     }
  2556.     
  2557.     this.style.backgroundImage = image;
  2558. }
  2559.  
  2560. function ButtonOnOut()
  2561. {
  2562.     var image    = FMCGetMCAttribute( this, "MadCap:outImage" );
  2563.     
  2564.     if ( !image.StartsWith( "url", false ) || !image.EndsWith( ")", false ) )
  2565.     {
  2566.         image = FMCCreateCssUrl( image );
  2567.     }
  2568.     
  2569.     this.style.backgroundImage = image;
  2570. }
  2571.  
  2572. function ButtonOnDown()
  2573. {
  2574.     StartPress( this ); return false;
  2575. }
  2576.  
  2577. function StartPress( node )
  2578. {
  2579.     // Debug
  2580.     //window.status += "s";
  2581.     
  2582.     gButton = node;
  2583.     
  2584.     if ( document.body.setCapture )
  2585.     {
  2586.         document.body.setCapture();
  2587.         
  2588.         document.body.onmousemove = Press;
  2589.         document.body.onmouseup = EndPress;
  2590.     }
  2591.     else if ( document.addEventListener )
  2592.     {
  2593.         document.addEventListener( "mousemove", Press, true );
  2594.         document.addEventListener( "mouseup", EndPress, true );
  2595.     }
  2596.     
  2597.     gButton.style.backgroundImage = FMCCreateCssUrl( FMCGetMCAttribute( gButton, "MadCap:selectedImage" ) );
  2598.     gButton.onmouseover = function() { this.style.backgroundImage = FMCCreateCssUrl( FMCGetMCAttribute( this, "MadCap:selectedImage" ) ); };
  2599. }
  2600.  
  2601. function Press( e )
  2602. {
  2603.     // Debug
  2604.     //window.status += "p";
  2605.     
  2606.     if ( !e )
  2607.     {
  2608.         e = window.event;
  2609.         target = e.srcElement;
  2610.     }
  2611.     else if ( e.target )
  2612.     {
  2613.         target = e.target;
  2614.     }
  2615.     
  2616.     if ( target == gButton )
  2617.     {
  2618.         gButton.style.backgroundImage = FMCCreateCssUrl( FMCGetMCAttribute( gButton, "MadCap:selectedImage" ) );
  2619.     }
  2620.     else
  2621.     {
  2622.         gButton.style.backgroundImage = FMCCreateCssUrl( FMCGetMCAttribute( gButton, "MadCap:outImage" ) );
  2623.     }
  2624. }
  2625.  
  2626. function EndPress( e )
  2627. {
  2628.     // Debug
  2629.     //window.status += "e";
  2630.     
  2631.     var target  = null;
  2632.     
  2633.     if ( !e )
  2634.     {
  2635.         e = window.event;
  2636.         target = e.srcElement;
  2637.     }
  2638.     else if ( e.target )
  2639.     {
  2640.         target = e.target;
  2641.     }
  2642.     
  2643.     if ( target == gButton )
  2644.     {
  2645.         // Debug
  2646.         //window.status += "c";
  2647.         
  2648.         gButton.style.backgroundImage = FMCCreateCssUrl( FMCGetMCAttribute( gButton, "MadCap:overImage" ) );
  2649.     }
  2650.     
  2651.     gButton.onmouseover = function() { this.style.backgroundImage = FMCCreateCssUrl( FMCGetMCAttribute( this, "MadCap:overImage" ) ); };
  2652.     
  2653.     if ( document.body.releaseCapture )
  2654.     {
  2655.         document.body.releaseCapture();
  2656.         
  2657.         document.body.onmousemove = null;
  2658.         document.body.onmouseup = null;
  2659.     }
  2660.     else if ( document.removeEventListener )
  2661.     {
  2662.         document.removeEventListener( "mousemove", Press, true );
  2663.         document.removeEventListener( "mouseup", EndPress, true );
  2664.     }
  2665.     
  2666.     gButton = null;
  2667. }
  2668.  
  2669. //
  2670. //    End button effects
  2671. //
  2672.  
  2673. //
  2674. //    String helpers
  2675. //
  2676.  
  2677. String.prototype.IsNullOrEmpty = function()
  2678. {
  2679.     if ( this == null )
  2680.     {
  2681.         return true;
  2682.     }
  2683.     
  2684.     if ( this.length == 0 )
  2685.     {
  2686.         return true;
  2687.     }
  2688.     
  2689.     return false;
  2690. }
  2691.  
  2692. String.prototype.StartsWith = function( str, caseSensitive )
  2693. {
  2694.     if ( str == null )
  2695.     {
  2696.         return false;
  2697.     }
  2698.     
  2699.     if ( this.length < str.length )
  2700.     {
  2701.         return false;
  2702.     }
  2703.     
  2704.     var value1    = this;
  2705.     var value2    = str;
  2706.     
  2707.     if ( !caseSensitive )
  2708.     {
  2709.         value1 = value1.toLowerCase();
  2710.         value2 = value2.toLowerCase();
  2711.     }
  2712.     
  2713.     if ( value1.substring( 0, value2.length ) == value2 )
  2714.     {
  2715.         return true;
  2716.     }
  2717.     else
  2718.     {
  2719.         return false;
  2720.     }
  2721. }
  2722.  
  2723. String.prototype.EndsWith = function( str, caseSensitive )
  2724. {
  2725.     if ( str == null )
  2726.     {
  2727.         return false;
  2728.     }
  2729.     
  2730.     if ( this.length < str.length )
  2731.     {
  2732.         return false;
  2733.     }
  2734.     
  2735.     var value1    = this;
  2736.     var value2    = str;
  2737.     
  2738.     if ( !caseSensitive )
  2739.     {
  2740.         value1 = value1.toLowerCase();
  2741.         value2 = value2.toLowerCase();
  2742.     }
  2743.     
  2744.     if ( value1.substring( value1.length - value2.length ) == value2 )
  2745.     {
  2746.         return true;
  2747.     }
  2748.     else
  2749.     {
  2750.         return false;
  2751.     }
  2752. }
  2753.  
  2754. String.prototype.Contains = function( str, caseSensitive )
  2755. {
  2756.     var value1    = this;
  2757.     var value2    = str;
  2758.     
  2759.     if ( !caseSensitive )
  2760.     {
  2761.         value1 = value1.toLowerCase();
  2762.         value2 = value2.toLowerCase();
  2763.     }
  2764.     
  2765.     return value1.indexOf( value2 ) != -1;
  2766. }
  2767.  
  2768. String.prototype.Equals = function( str, caseSensitive )
  2769. {
  2770.     var value1    = this;
  2771.     var value2    = str;
  2772.     
  2773.     if ( !caseSensitive )
  2774.     {
  2775.         value1 = value1.toLowerCase();
  2776.         value2 = value2.toLowerCase();
  2777.     }
  2778.     
  2779.     return value1 == value2;
  2780. }
  2781.  
  2782. String.prototype.CountOf = function( str, caseSensitive )
  2783. {
  2784.     var count    = 0;
  2785.     var value1    = this;
  2786.     var value2    = str;
  2787.     
  2788.     if ( !caseSensitive )
  2789.     {
  2790.         value1 = value1.toLowerCase();
  2791.         value2 = value2.toLowerCase();
  2792.     }
  2793.     
  2794.     var lastIndex    = -1;
  2795.     
  2796.     while ( true )
  2797.     {
  2798.         lastIndex = this.indexOf( str, lastIndex + 1 );
  2799.         
  2800.         if ( lastIndex == -1 )
  2801.         {
  2802.             break;
  2803.         }
  2804.         
  2805.         count++;
  2806.     }
  2807.     
  2808.     return count;
  2809. }
  2810.  
  2811. //
  2812. //    End String helpers
  2813. //
  2814.